home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / prolog / modprolg / mod-prol.lha / Prolog / modlib / src / $read.P < prev    next >
Encoding:
Text File  |  1992-05-20  |  31.6 KB  |  890 lines

  1. %   File   : READ.PL
  2. %   Author : D.H.D.Warren + Richard O'Keefe
  3. %   Modified for SB-Prolog by Saumya K. Debray & Deeporn Beardsley
  4. %   Updated: July 1988
  5. %   Purpose: Read Prolog terms in Dec-10 syntax.
  6. /*
  7.     Modified by Alan Mycroft to regularise the functor modes.
  8.     This is both easier to understand (there are no more '?'s),
  9.     and also fixes bugs concerning the curious interaction of cut with
  10.     the state of parameter instantiation.
  11.  
  12.     Since this file doesn't provide "metaread", it is considerably
  13.     simplified.  The token list format has been changed somewhat, see
  14.     the comments in the RDTOK file.
  15.  
  16.     I have added the rule X(...) -> apply(X,[...]) for Alan Mycroft.
  17. */
  18.  
  19. /****************************************************************************
  20.  *                                                                          *
  21.  * This file has been changed by to include Modules Extensions              *
  22.  * Changes by : Brian Paxton 1991/92                                        *
  23.  * Last update : June 1992                                                  *
  24.  *                                                                          *
  25.  * Organisation : University of Edinburgh.                                  *
  26.  * For : Departments of Computer Science and Artificial Intelligence        * 
  27.  *       Fourth Year Project.                                               *
  28.  *                                                                          *
  29.  ****************************************************************************/
  30.  
  31. $read_export([$read/1,$read/2,$read_module/1,$read/3]). 
  32.  
  33. % $read_use : $bmeta, $meta, $bio, $io, $blist, $retr, $name, $modules
  34.  
  35. %   $read(?Answer). 
  36.  
  37. $read(Answer) :- $read(Answer, _, perv). 
  38.  
  39. %   $read(?Answer, ?Arg)
  40. %   reads a term from the current input stream. Arg may be the list of 
  41. %   variables in the expression (a list of [Atom=Variable] pairs) or a 
  42. %   structure tag.
  43.  
  44. $read(Answer, Variables) :-
  45.     var(Variables), !,
  46.     $read(Answer, Variables, perv).
  47.  
  48. $read(Answer, Tag) :-
  49.     $isa_structuretag(Tag),
  50.     $read(Answer, _, Tag).
  51.  
  52. %   $read(?Answer, -Vars, ?Str)
  53. %   Read Answer from the standard input with respect to the structure Str,
  54. %   giving a list of variables Vars.
  55.  
  56. $read(Answer,Variables,Tag) :-
  57.     ( $isa_structuretag(Tag) -> 
  58.         ( repeat,
  59.           $read_tokens(Tokens, Variables),
  60.           ( Tag == perv -> Tokens1 = Tokens ;
  61.                            $dereference_input(Tokens, Tokens1, Tag) ),
  62.           ( ( $read(Tokens1, 1200, Term, Leftover, Tag),
  63.               $read_all(Leftover) ;
  64.               $read_syntax_error(Tokens1) ) ),
  65.           !,
  66.           Term = Answer ) ;
  67.         ( $writename('*** Error : Third argument to read/3 must be a structure tag'),
  68.           $nl, fail ) ).
  69.  
  70. %   $dereference_input(+Tokens, -New, +Tag)
  71. %
  72. % Once the tokens have been read in, this routine is called to pre-process
  73. % any colons (:) in the input into the correct dereferenced item. All
  74. % paths must be written in the infix : notation. After processing, the result
  75. % is a list of tokens like the original list, but any paths have been 
  76. % changed into an atom with the correct structure tag which can be passed
  77. % on to the original read processing routines.
  78.  
  79. $dereference_input([], [], _).
  80. $dereference_input([atom(Atom), atom(':')|Tail],[atom(Newatom)|Newtail],Tag) :-
  81.     $get_path([atom(Atom), atom(':')|Tail], Path, Function, Leftover), !,
  82.     $dereference_path(Path, Function, Newatom, Tag),
  83.     $dereference_input(Leftover, Newtail, Tag).
  84. $dereference_input([atom(':')|_], _, _) :- !,
  85.     $writename('** Error : Illegal use of : path constructor'),
  86.     $nl, fail.
  87. $dereference_input([Head|Tail], [Head|Newtail], Tag) :- !,
  88.     $dereference_input(Tail, Newtail, Tag).
  89.  
  90. $get_path([atom(Atom1), atom(':'), atom(Atom2), atom(':')|Tail],
  91.       Atom1:Path, Function, Leftover) :-
  92.     $get_path([atom(Atom2), atom(':')|Tail], Path, Function, Leftover).
  93. $get_path([atom(Atom1), atom(':'), atom(Atom2)|Tail], Atom1, Atom2, Tail).
  94.  
  95. $dereference_path(Path, Item, Newitem, Strtag) :-
  96.         $module_structure(_,Strtag,Substrs,_,_),
  97.     $memberchk(Path ---> Tag, Substrs) ->
  98.         $dismantle_name(Newitem, Item, Tag) ;
  99.         ( $writename('*** Error: Unknown structure '),
  100.               $write(Path),
  101.           $writename(' during read'),
  102.               $nl, fail ).
  103.  
  104.  
  105. %   $read_all(+Tokens)
  106. $read_all([]) :- !. 
  107. $read_all(S) :-
  108.         $read_syntax_error(['operator expected after expression'], S). 
  109.  
  110.  
  111. %   $read_expect(Token, TokensIn, TokensOut)
  112. %   reads the next token, checking that it is the one expected, and
  113. %   giving an error message if it is not.  It is used to look for
  114. %   right brackets of various sorts, as they're all we can be sure of. 
  115.  
  116. $read_expect(Token, [Token|Rest], Rest) :- !. 
  117. $read_expect(Token, S0, _) :-
  118.         $read_syntax_error([Token,'or operator expected'], S0). 
  119.  
  120.  
  121. %   I want to experiment with having the operator information held as
  122. %   ordinary Prolog facts.  For the moment the following predicates
  123. %   remain as interfaces to curr_op. 
  124. %   $read_prefixop(O -> Self, Rarg)
  125. %   $read_postfixop(O -> Larg, Self)
  126. %   $read_infixop(O -> Larg, Self, Rarg)
  127.  
  128. % Note that to perform this next predicate in the modules environment, we
  129. % need to pass in the current structure tag and return the name of the
  130. % operator (which is not necessarily the one passed in - it may now
  131. % have a tag).
  132.  
  133.  
  134. $check_mapped(F1,Arity,F2,Tag) :-
  135.     $symtype($mapped_function(_,_,_,_), Type),
  136.     ( ( Type > 0, $mapped_function(F1,Arity,F2,_) ) ;  % &&
  137.       F2 = F1 ),!.
  138.  
  139. % Purpose of line ** and similar ones :
  140. % If the operator under consideration has not yet been tagged it is either,
  141. % a pervasive operator of the desired type or a operator from the current
  142. % structure of the required type (or neither). This code first tries the
  143. % current structure operator, then the pervasive one.
  144.  
  145. $read_prefixop(F0, F2, X, Y, Tag) :- 
  146.     ( ( $dismantle_name(F0, _, perv), $dismantle_name(F1, F0, Tag) ) ;  %**
  147.       F1 = F0 ),
  148.     $read_prefixop(F1, X, Y),
  149.     $check_mapped(F1,1,F2,Tag), !.
  150.  
  151. $read_prefixop(Op, Prec, Prec) :-
  152.         $read_curr_op(Prec, fy, Op), !. 
  153. $read_prefixop(Op, Prec, Less) :-
  154.         $read_curr_op(Prec, fx, Op), !,
  155.         Less is Prec-1. 
  156.  
  157. $read_postfixop(F0, F2, Prec, Prec1, Tag) :-
  158.     ( ( $dismantle_name(F0, _, perv), $dismantle_name(F1, F0, Tag) ) ;
  159.       F1 = F0 ),
  160.     $read_postfixop(F1, Prec, Prec1),
  161.     $check_mapped(F1,1,F2,Tag), !.
  162.  
  163. $read_postfixop(Op, Prec, Prec) :-
  164.         $read_curr_op(Prec, yf, Op), !. 
  165. $read_postfixop(Op, Less, Prec) :-
  166.         $read_curr_op(Prec, xf, Op), !, Less is Prec-1. 
  167.  
  168. $read_infixop(F0, F2, X, Y, Z, Tag) :-
  169.     ( ( $dismantle_name(F0, _, perv), $dismantle_name(F1, F0, Tag) ) ;
  170.       F1 = F0 ),
  171.     $read_infixop(F1, X, Y, Z),
  172.     $check_mapped(F1,2,F2,Tag), !.
  173.  
  174. $read_infixop(Op, Less, Prec, Less) :-
  175.         $read_curr_op(Prec, xfx, Op), !, Less is Prec-1. 
  176. $read_infixop(Op, Less, Prec, Prec) :-
  177.         $read_curr_op(Prec, xfy, Op), !, Less is Prec-1. 
  178. $read_infixop(Op, Prec, Prec, Less) :-
  179.         $read_curr_op(Prec, yfx, Op), !, Less is Prec-1. 
  180.  
  181.  
  182. $read_ambigop(F, F1, F2, L1, O1, R1, L2, O2, Tag) :-
  183.         $read_postfixop(F, F1, L2, O2, Tag),
  184.         $read_infixop(F, F2, L1, O1, R1, Tag), !. 
  185.  
  186.  
  187. %   $read(+TokenList, +Precedence, -Term, -LeftOver, +Tag)
  188. %   parses a Token List in a context of given Precedence,
  189. %   returning a Term and the unread Left Over tokens.
  190.  
  191. :- mode($read,5,[nv,nv,d,d,d]).
  192.  
  193.  
  194. $read([Token|RestTokens], Precedence, Term, LeftOver, Tag) :-
  195.         $read(Token, RestTokens, Precedence, Term, LeftOver, Tag).
  196. $read([], _, _, _, _) :-
  197.         $read_syntax_error(['expression expected'], []).
  198.  
  199.  
  200. %   $read(+Token, +RestTokens, +Precedence, -Term, -LeftOver, +Tag)
  201. %   Renamed as well.
  202.  
  203. :- mode($read,6,[nv,nv,c,d,d,d]).
  204.  
  205. $read(var(Variable,_), ['('|S1], Precedence, Answer, S, Tag) :- !,
  206.         $read(S1, 999, Arg1, S2, Tag),
  207.         $read_args(S2, RestArgs, S3, Tag), !,
  208.         $read_exprtl0(S3,apply(Variable,[Arg1|RestArgs]),Precedence,Answer,S,
  209.                   Tag).
  210.  
  211. $read(var(Variable,_), S0, Precedence, Answer, S, Tag) :- !,
  212.         $read_exprtl0(S0, Variable, Precedence, Answer, S, Tag).
  213.  
  214. $read(atom(-), [number(Num)|S1], Precedence, Answer, S, Tag) :-
  215.         Negative is -Num, !,
  216.         $read_exprtl0(S1, Negative, Precedence, Answer, S, Tag).
  217.  
  218. $read(atom(Functor), ['('|S1], Precedence, Answer, S, Tag) :- !,
  219.         $read(S1, 999, Arg1, S2, Tag),
  220.         $read_args(S2, RestArgs, S3, Tag),
  221.     $length([Arg1|RestArgs],Arity),
  222.     ( $pervasive(Functor/Arity) -> 
  223.           Functor0 = Functor ;
  224.           ( $dismantle_name(Functor, _, Oldtag),
  225.             ( Oldtag == perv -> $dismantle_name(Functor0, Functor, Tag) ;
  226.                             Functor0 = Functor ) ) ),
  227.     $check_mapped(Functor0,Arity,Functor1,Tag),
  228.         $univ(Term,[Functor1,Arg1|RestArgs]), !,
  229.         $read_exprtl0(S3, Term, Precedence, Answer, S, Tag).
  230.  
  231. $read(atom(Functor), S0, Precedence, Answer, S, Tag) :-
  232.         $read_prefixop(Functor, Functor1, Prec, Right, Tag), !,
  233.         $read_aft_pref_op(Functor1, Functor, Prec, Right, S0, Precedence, 
  234.                       Answer, S, Tag).
  235.  
  236. $read(atom(Atom), S0, Precedence, Answer, S, Tag) :- !,
  237.     ( $pervasive0(Atom) -> 
  238.           Atom0 = Atom ;
  239.           ( $dismantle_name(Atom, _, Oldtag),
  240.             ( Oldtag == perv -> $dismantle_name(Atom0, Atom, Tag) ;
  241.                             Atom0 = Atom ) ) ),
  242.     $check_mapped(Atom0,0,Atom1,Tag),
  243.         $read_exprtl0(S0, Atom1, Precedence, Answer, S, Tag).
  244.  
  245. $read(number(Num), S0, Precedence, Answer, S, Tag) :- !,
  246.         $read_exprtl0(S0, Num, Precedence, Answer, S, Tag).
  247.  
  248. $read('[', [']'|S1], Precedence, Answer, S, Tag) :- !,
  249.         $read_exprtl0(S1, [], Precedence, Answer, S, Tag).
  250.  
  251. $read('[', S1, Precedence, Answer, S, Tag) :- !,
  252.         $read(S1, 999, Arg1, S2, Tag),
  253.         $read_list(S2, RestArgs, S3, Tag), !,
  254.         $read_exprtl0(S3, [Arg1|RestArgs], Precedence, Answer, S, Tag).
  255.  
  256. $read('(', S1, Precedence, Answer, S, Tag) :- !,
  257.         $read(S1, 1200, Term, S2, Tag),
  258.         $read_expect(')', S2, S3), !,
  259.         $read_exprtl0(S3, Term, Precedence, Answer, S, Tag).
  260.  
  261. $read(' (', S1, Precedence, Answer, S, Tag) :- !,
  262.         $read(S1, 1200, Term, S2, Tag),
  263.         $read_expect(')', S2, S3), !,
  264.         $read_exprtl0(S3, Term, Precedence, Answer, S, Tag).
  265.  
  266. $read('{', ['}'|S1], Precedence, Answer, S, Tag) :- !,
  267.         $read_exprtl0(S1, '{}', Precedence, Answer, S, Tag).
  268.  
  269. $read('{', S1, Precedence, Answer, S, Tag) :- !,
  270.         $read(S1, 1200, Term, S2, Tag),
  271.         $read_expect('}', S2, S3), !,
  272.         $read_exprtl0(S3, '{}'(Term), Precedence, Answer, S, Tag).
  273.  
  274. $read(string(List), S0, Precedence, Answer, S, Tag) :- !,
  275.         $read_exprtl0(S0, List, Precedence, Answer, S, Tag).
  276.  
  277. $read(Token, S0, _, _, _, _) :-
  278.         $read_syntax_error([Token,'cannot start an expression'], S0).
  279.  
  280.  
  281. %   $read_args(+Tokens, -TermList, -LeftOver, +Tag)
  282. %   parses {',' expr(999)} ')' and returns a list of terms.
  283.  
  284. $read_args([Tok|S1], Term, S, Tag) :-
  285.         '_$savecp'(CP),
  286.         $read_args1(Tok,Term,S,S1,CP, Tag), '_$cutto'(CP).
  287. $read_args(S, _, _, _) :-
  288.         $read_syntax_error([', or ) expected in arguments'], S).
  289.  
  290. :- mode($read_args1,6,[c,nv,d,d,d,d]).
  291.  
  292. $read_args1(',',[Term|Rest],S,S1,CP, Tag) :- 
  293.         $read(S1, 999, Term, S2, Tag), '_$cutto'(CP),
  294.         $read_args(S2, Rest, S, Tag).
  295. $read_args1(')',[],S,S,_,_).
  296.  
  297.  
  298.  
  299. %   $read_list(+Tokens, -TermList, -LeftOver, +Tag)
  300. %   parses {',' expr(999)} ['|' expr(999)] ']' and returns a list of terms.
  301.  
  302. $read_list([Tok|S1],Term,S, Tag) :-
  303.         '_$savecp'(CP),
  304.         $read_list1(Tok,Term,S,S1,CP, Tag),
  305.         '_$cutto'(CP).
  306. $read_list(S, _, _, _) :-
  307.         $read_syntax_error([', | or ] expected in list'], S).
  308.  
  309.  
  310. :- mode($read_list1,6,[c,nv,d,d,d,d]).
  311.  
  312. $read_list1(',',[Term|Rest],S,S1,CP, Tag) :-
  313.         $read(S1, 999, Term, S2, Tag), '_$cutto'(CP),
  314.         $read_list(S2, Rest, S, Tag).
  315. $read_list1('|',Rest,S,S1,CP, Tag) :-
  316.         $read(S1, 999, Rest, S2, Tag), '_$cutto'(CP),
  317.         $read_expect(']', S2, S).
  318. $read_list1(']',[],S,S,_,_).
  319.  
  320.  
  321. %   $read_aft_pref_op(+Op, +Oldop, +Prec, +ArgPrec, +Rest, +Precedence, -Ans, 
  322. %                     -LeftOver, +Tag)
  323. %
  324. % Since an operators internal name can be different from its typed name in
  325. % modular Prolog (because of a mapped function), we pass the typed name in
  326. % here just is case it turns out not to be an operator after all.
  327.  
  328. :- mode($read_aft_pref_op,9,[nv,nv,nv,nv,nv,nv,d,d,d]).
  329.  
  330. $read_aft_pref_op(Op, _, Oprec, Aprec, S0, Precedence, _, _, _) :-
  331.         Precedence < Oprec, !,
  332.         $read_syntax_error(['prefix operator',Op,'in context with precedence '
  333.                         ,Precedence], S0).
  334.  
  335. $read_aft_pref_op(Op, Oldop, Oprec, Aprec, S0, Precedence, Answer, S, Tag) :-
  336.         $read_peepop(S0, S1, Tag),
  337.         $read_prefix_is_atom(S1, Oprec), % can't cut but would like to
  338.     ( $pervasive0(Oldop) -> 
  339.           Oldop0 = Oldop ;
  340.           ( $dismantle_name(Oldop, _, Oldtag),
  341.             ( Oldtag == perv -> $dismantle_name(Oldop0, Oldop, Tag) ;
  342.                             Oldop0 = Oldop ) ) ),
  343.     $check_mapped(Oldop0,0,Oldop1,Tag),
  344.         $read_exprtl(S1, Oprec, Oldop1, Precedence, Answer, S, Tag).
  345.  
  346. $read_aft_pref_op(Op, _, Oprec, Aprec, S1, Precedence, Answer, S, Tag) :-
  347.         $read(S1, Aprec, Arg, S2, Tag),
  348.         $univ(Term,[Op,Arg]), !,
  349.         $read_exprtl(S2, Oprec, Term, Precedence, Answer, S, Tag).
  350.  
  351.  
  352. %   The next clause fixes a bug concerning "mop dop(1,2)" where
  353. %   mop is monadic and dop dyadic with higher Prolog priority.
  354.  
  355. $read_peepop([atom(F),'('|S1], [atom(F),'('|S1], Tag) :- !.
  356. $read_peepop([atom(F)|S1], [infixop(F0,L,P,R)|S1], Tag) :- 
  357.         $read_infixop(F, F0, L, P, R, Tag).
  358. $read_peepop([atom(F)|S1], [postfixop(F0,L,P)|S1], Tag) :- 
  359.         $read_postfixop(F, F0, L, P, Tag).
  360. $read_peepop(S0, S0, _).
  361.  
  362.  
  363. %   $read_prefix_is_atom(+TokenList, +Precedence)
  364. %   is true when the right context TokenList of a prefix operator
  365. %   of result precedence Precedence forces it to be treated as an
  366. %   atom, e.g. (- = X), p(-), [+], and so on.
  367.  
  368. $read_prefix_is_atom([Token|_], Precedence) :-
  369.         $read_prefix_is_atom(Token, Precedence).
  370.  
  371. $read_prefix_is_atom(infixop(_,L,_,_), P) :- L >= P.
  372. $read_prefix_is_atom(postfixop(_,L,_), P) :- L >= P.
  373. $read_prefix_is_atom(')', _).
  374. $read_prefix_is_atom(']', _).
  375. $read_prefix_is_atom('}', _).
  376. $read_prefix_is_atom('|', P) :- 1100 >= P.
  377. $read_prefix_is_atom(',', P) :- 1000 >= P.
  378. $read_prefix_is_atom([],  _).
  379.  
  380.  
  381. %   $read_exprtl0(+Tokens, +Term, +Prec, -Answer, -LeftOver, +Tag)
  382. %   is called by read/4 after it has read a primary (the Term).
  383. %   It checks for following postfix or infix operators.
  384.  
  385.  
  386. $read_exprtl0([atom(F)|S1], Term, Precedence, Answer, S, Tag) :-
  387.     $read_ambigop(F, F1, F2, L1, O1, R1, L2, O2, Tag), !,
  388.     (   $read_exprtl([infixop(F2,L1,O1,R1)|S1],0,Term,Precedence,Answer,S,
  389.                      Tag)
  390.     ;   $read_exprtl([postfixop(F1,L2,O2) |S1],0,Term,Precedence,Answer,S,
  391.                      Tag)
  392.     ).
  393. $read_exprtl0([atom(F)|S1], Term, Precedence, Answer, S, Tag) :-
  394.     $read_infixop(F, F0, L1, O1, R1, Tag), !,
  395.     $read_exprtl([infixop(F0,L1,O1,R1)|S1],0,Term,Precedence,Answer,S,Tag).
  396. $read_exprtl0([atom(F)|S1], Term, Precedence, Answer, S, Tag) :-
  397.     $read_postfixop(F, F0, L2, O2, Tag), !,
  398.     $read_exprtl([postfixop(F0,L2,O2)|S1],0,Term,Precedence,Answer,S,Tag).
  399. $read_exprtl0([','|S1], Term, Precedence, Answer, S, Tag) :-
  400.     Precedence >= 1000, !,
  401.     $read(S1, 1000, Next, S2, Tag), !,
  402.     $read_exprtl(S2, 1000, (Term,Next), Precedence, Answer, S, Tag).
  403. $read_exprtl0(['|'|S1], Term, Precedence, Answer, S, Tag) :-
  404.     Precedence >= 1100, !,
  405.     $read(S1, 1100, Next, S2, Tag), !,
  406.     $read_exprtl(S2, 1100, (Term;Next), Precedence, Answer, S, Tag).
  407. $read_exprtl0([Thing|S1], _, _, _, _, _) :-
  408.     $read_cfexpr(Thing, Culprit), !,
  409.     $read_syntax_error([Culprit,follows,expression], [Thing|S1]).
  410. $read_exprtl0(S, Term, _, Term, S, _).
  411.  
  412. :- mode($read_cfexpr,2,[nv,d]).
  413.  
  414. $read_cfexpr(atom(_),       atom).
  415. $read_cfexpr(var(_,_),      variable).
  416. $read_cfexpr(number(_),     number).
  417. $read_cfexpr(string(_),     string).
  418. $read_cfexpr(' (',          bracket).
  419. $read_cfexpr('(',           bracket).
  420. $read_cfexpr('[',           bracket).
  421. $read_cfexpr('{',           bracket).
  422.  
  423.  
  424. :- mode($read_exprtl,7,[nv,d,d,c,d,d,d]).
  425.  
  426. $read_exprtl([infixop(F,L,O,R)|S1], C, Term, Precedence, Answer, S, Tag) :-
  427.     Precedence >= O, C =< L, !,
  428.     $read(S1, R, Other, S2, Tag),
  429.     $univ(Expr,[F,Term,Other]), /*!,*/
  430.     $read_exprtl(S2, O, Expr, Precedence, Answer, S, Tag).
  431. $read_exprtl([postfixop(F,L,O)|S1], C, Term, Precedence, Answer, S, Tag) :-
  432.     Precedence >= O, C =< L, !,
  433.     $univ(Expr,[F,Term]),
  434.     $read_peepop(S1, S2, Tag),
  435.     $read_exprtl(S2, O, Expr, Precedence, Answer, S, Tag).
  436. $read_exprtl([','|S1], C, Term, Precedence, Answer, S, Tag) :-
  437.     Precedence >= 1000, C < 1000, !,
  438.     $read(S1, 1000, Next, S2, Tag), /*!,*/
  439.     $read_exprtl(S2, 1000, (Term,Next), Precedence, Answer, S, Tag).
  440. $read_exprtl(['|'|S1], C, Term, Precedence, Answer, S, Tag) :-
  441.     Precedence >= 1100, C < 1100, !,
  442.     $read(S1, 1100, Next, S2, Tag), /*!,*/
  443.     $read_exprtl(S2, 1100, (Term;Next), Precedence, Answer, S, Tag).
  444. $read_exprtl(S, _, Term, _, Term, S, _).
  445.  
  446.  
  447. %   This business of syntax errors is tricky.  When an error is detected,
  448. %   we have to write out a message.  We also have to note how far it was
  449. %   to the end of the input, and for this we are obliged to use the data-
  450. %   base.  Then we fail all the way back to $read(), and that prints
  451. %   the input list with a marker where the error was noticed.  If subgoal_of
  452. %   were available in compiled code we could use that to find the input
  453. %   list without hacking the data base.  The really hairy thing is that
  454. %   the original code noted a possible error and backtracked on, so that
  455. %   what looked at first sight like an error sometimes turned out to be
  456. %   a wrong decision by the parser.  This version of the parser makes
  457. %   fewer wrong decisions, and $ goal was to get it to do no backtracking
  458. %   at all.  This goal has not yet been met, and it will still occasionally
  459. %   report an error message and then decide that it is happy with the input
  460. %   after all.  Sorry about that.
  461.  
  462. /*  Modified by Saumya Debray, Nov 18 1986, to use SB-Prolog's database
  463.     facilities to print out error messages.                             */
  464.  
  465. $read_syntax_error(Message, List) :-
  466.         $length(List,Length),
  467.         $symtype('_$synerr'(_),X),
  468.         ( (X =:= 0 ; not('_$synerr'(_))) ->     /* _$synerr/1 undefined */
  469.                 $assert('_$synerr'(Length)) ;
  470.                 true
  471.         ),
  472.         !,
  473.         fail.
  474.  
  475. $read_syntax_error(List) :-
  476.         $nl, $print('*** syntax error ***'), $nl,
  477.         '_$synerr'(AfterError),
  478.         $retract('_$synerr'(AfterError)),
  479.         $length(List,Length),
  480.         BeforeError is Length - AfterError,
  481.         $read_display_list(List,BeforeError), !,
  482.         fail.
  483.  
  484. $read_display_list(X, 0) :-
  485.         $print('<<here>> '), !,
  486.         $read_display_list(X, 99999).
  487. $read_display_list([Head|Tail], BeforeError) :-
  488.         $print_token(Head),
  489.         $writename(' '),
  490.         Left is BeforeError-1, !,
  491.         $read_display_list(Tail, Left).
  492. $read_display_list([], _) :-
  493.         $nl.
  494.  
  495.  
  496. $print_list([]) :- $nl.
  497. $print_list([Head|Tail]) :-
  498.         $tab(1),
  499.         $print_token(Head),
  500.         $print_list(Tail).
  501.  
  502. $print_token(atom(X))    :- !, $print(X).
  503. $print_token(var(V,X))   :- !, $print(X).
  504. $print_token(number(X)) :-  !, $print(X).
  505. $print_token(string(X))  :- !, $print(X).
  506. $print_token(X)          :-    $print(X).
  507.  
  508.  
  509. /*
  510. %   $read_tokens(TokenList, Dictionary)
  511. %   returns a list of tokens.  It is needed to "prime" read_tokens/2
  512. %   with the initial blank, and to check for end of file.  The
  513. %   Dictionary is a list of AtomName=Variable pairs in no particular order.
  514. %   The way end of file is handled is that everything else FAILS when it
  515. %   hits character "-1", sometimes printing a warning.  It might have been
  516. %   an idea to return the atom 'end_of_file' instead of the same token list
  517. %   that you'd have got from reading "end_of_file. ", but (1) this file is
  518. %   for compatibility, and (b) there are good practical reasons for wanting
  519. %   this behaviour. */
  520.  
  521. $read_tokens(TokenList, Dictionary) :-
  522.         $read_next_token(Type,Value),
  523.     $read_insert_token(Type,Value,Dict,ListOfTokens),
  524.         $append(Dict, [], Dict), !, /*  fill in the "hole" at the end */
  525.         Dictionary = Dict,              /*  unify explicitly so we read and */
  526.         TokenList = ListOfTokens.       /*  then check even with filled in */
  527.                                         /*  arguments */
  528. $read_tokens([atom(end_of_file)], []).   /*  only thing that can go wrong */
  529.  
  530. $read_next_token(Type, Value) :- '_$builtin'(135).
  531.  
  532. $read_insert_token(X,Val,Dict,Tokens):-            
  533.   (X=:=0 ->
  534.       /**0**/                           /* punctuation */
  535.       (Tokens = [Val | TokRest],
  536.        $read_next_token(Type,Value),
  537.        $read_insert_token(Type,Value,Dict,TokRest)
  538.       );
  539.       (X<3 ->
  540.      (X=:=1 ->                      /* var */
  541.         /**1**/
  542.         (Val = Name, Tokens = [var(Var,Name) | TokRest], 
  543.          $read_lookup(Dict, Name=Var),
  544.          $read_next_token(Type,Value), 
  545.          $read_insert_token(Type,Value,Dict,TokRest)
  546.         );
  547.         /**2**/                    /* atom( */
  548.         (Tokens = [atom(Val) | ['(' | TokRest]],
  549.              $read_next_token(Type,Value),
  550.          $read_insert_token(Type,Value,Dict,TokRest)
  551.         )
  552.      );
  553.      (X<5 ->
  554.         (X=:=3 ->
  555.            /**3**/                /* number */
  556.            (Tokens = [number(Val) | TokRest],
  557.             $read_next_token(Type,Value),
  558.             $read_insert_token(Type,Value,Dict,TokRest)
  559.            ) ;
  560.            /**4**/                /* atom */
  561.            (Tokens = [atom(Val) | TokRest],
  562.             $read_next_token(Type,Value),
  563.          $read_insert_token(Type,Value,Dict,TokRest)
  564.            )
  565.         );
  566.         (X<7 ->
  567.            (X=:=5 ->
  568.            /**5**/                /* end of clause */
  569.            Tokens = [] ;
  570.            /**6**/            /* uscore */
  571.            (Tokens = [var(_,Val) | TokRest],
  572.             $read_next_token(Type,Value),
  573.                 $read_insert_token(Type,Value,Dict,TokRest)
  574.            )
  575.            ) ;
  576.            (X=:=7 ->
  577.            /**7**/            /* semicolon */
  578.            (Tokens = [atom((';')) | TokRest],
  579.             $read_next_token(Type,Value),
  580.                 $read_insert_token(Type,Value,Dict,TokRest)
  581.            );
  582.                  (X=:=8 ->
  583.                /**8**/            /* end of file */
  584.                fail ;
  585.                /**9**/            /* string */
  586.                (Tokens = [string(Val) | TokRest],
  587.                 $read_next_token(Type,Value),
  588.             $read_insert_token(Type,Value,Dict,TokRest)
  589.                )
  590.            )
  591.            )
  592.         )
  593.          )
  594.       )
  595.   ).
  596.  
  597.  
  598. %   read_lookup is identical to memberchk except for argument order and
  599. %   mode declaration.
  600.  
  601. $read_lookup([X|_], X) :- !.
  602. $read_lookup([_|T], X) :- $read_lookup(T, X).
  603.  
  604. /*
  605.   The rest of this file is concerned with reading in entire module
  606.   constructs into one term.
  607.   eg.   structure test/sig1 = struct
  608.                                  fun fun1/0.
  609.                                  test(fun1).
  610.                               end.
  611.       is returned as the term
  612.             structure('='('/'(test,sig1),[fun('/'(fun1,0)),test(fun1)]))
  613.       which is the same as
  614.             structure test/sig1 = [fun fun1/0,test(fun1)]
  615. */
  616.  
  617. % $read_module/1
  618. %
  619. % Read in an entire module construct.
  620.  
  621. $read_module(Answer) :-
  622.         repeat,
  623.         $read_tokens(Tokens, _),
  624.         $process_tokens(Tokens, Term), !,
  625.         Answer = Term.
  626.  
  627. % $process_tokens/2
  628. %
  629. % Check for signature, structure or functor declarations, if none, then
  630. % process as if it is a standard term.
  631.  
  632. $process_tokens([atom(signature)|Tail], Term) :- !,
  633.         $get_signature(Tail, Term).
  634.  
  635. $process_tokens([atom(structure)|Tail], Str) :- !,
  636.         $get_structure_head(Tail, Head, Leftover),
  637.         ( $get_strexpr(Leftover, Body, Sig, []) ->
  638.                ( Sig == $dummy -> Str = (structure Head = Body) ;
  639.                                   Str = (structure Head = Body/Sig) ) ;
  640.                ( $writename('** Read Error : Bad structure declaration for '),
  641.                  $write(Head), $nl, fail ) ).
  642.  
  643. $process_tokens([atom(functor)|Tail], Fun) :- !,
  644.         $get_functor_head(Tail, Head, Leftover),
  645.         ( $get_strexpr(Leftover, Body, Sig, []) ->
  646.                ( Sig == $dummy -> Fun = (functor Head = Body) ;
  647.                                   Fun = (functor Head = Body/Sig) ) ;
  648.                ( $writename('** Read Error : Bad functor declaration for '),
  649.                  $write(Head), $nl, fail ) ).
  650.  
  651. $process_tokens(Tokens, Term) :-
  652.         $read(Tokens, 1200, Term, Leftover, perv),
  653.         $read_all(Leftover).
  654.  
  655. $process_tokens(Tokens, _) :-
  656.         $read_syntax_error(Tokens).
  657.  
  658. % $get_signature/2
  659. %
  660. % Read in the head of a signature declaration.
  661.  
  662. $get_signature([atom(Atid), atom('='), atom(Atid2)], 
  663.                (signature Atid = Atid2) ) :- !.
  664. % ie.  signature X = Y.
  665.  
  666. $get_signature([atom(Atid), atom('='), atom(sig)|Spec],
  667.                (signature Atid = Speclist) ) :- !,
  668.         $get_speclist(Spec, Speclist, []).
  669. % ie.  signature X = sig ... end.
  670.  
  671. $get_signature([atom(Atid)|_], _) :- !,
  672.         $writename('** Read Error : Bad signature declaration for '),
  673.         $writename(Atid), $nl, fail.
  674.  
  675. $get_signature(_, _) :- !,
  676.         $writename('** Read Error : Bad signature declaration'), $nl, fail.
  677.  
  678. % $get_speclist/3
  679. %
  680. % Read the signature body into a list.
  681.  
  682. $get_speclist([atom(end_of_file)|_], _, _) :- !,
  683.         $writename('** Read Error : Unexpected end-of-file in signature body'),
  684.     $nl, fail.
  685.  
  686. $get_speclist([atom(end)|Rest], [], Leftover) :- !,
  687.         Rest = Leftover.
  688.  
  689. $get_speclist([atom(structure)|Tail], [structure(Term)|List], Left) :- !,
  690.     $get_structure_spec(Tail, Term) ->
  691.          $get_speclist(List, Left) ;
  692.          ( $writename('** Read Error : Bad structure spec in signature body'),
  693.            $nl, fail ).
  694.  
  695. $get_speclist(Tokens0, [Term|List], Left) :-
  696.         $read_on_failure(Tokens0, Tokens),
  697.         $read(Tokens, 1200, Term, Leftover, perv),
  698.          % Note we use the standard read routines here. There cannot be
  699.              % nested module constructs within a signature.
  700.         $read_all(Leftover), !,
  701.         $get_speclist(List, Left).
  702.  
  703. $get_speclist(List, Left) :-
  704.         $read_tokens(Tokens, _),
  705.         $get_speclist(Tokens, List, Left).
  706.  
  707. % $get_structure_spec/2
  708. %
  709. % Get the 'structure specstrb and ... and specstrb' part of the input.
  710.  
  711. $get_structure_spec([atom(Str), atom('/'), atom(Sig)|Rest], Term) :-
  712.     ( Sig = sig -> $get_speclist(Rest, Sig1, Rest1) ;
  713.                    ( Sig1 = Sig, Rest1 = Rest ) ),
  714.     ( Rest1 = [] -> Term = Str/Sig1 ;
  715.                    ( Rest1 = [atom(and)|Tail],
  716.                  $get_structure_spec(Tail, Term2),
  717.              Term = and(Str/Sig1, Term2) ) ).
  718.  
  719. % $read_on_failure/2
  720. %
  721.  
  722. $read_on_failure(Dec, Dec).
  723. $read_on_failure(_, Tokens) :-
  724.         $read_tokens(Readin, _),
  725.         $read_on_failure(Readin, Tokens).
  726.  
  727. % $get_structure_head/3
  728. %
  729. % Accept the head of a structure declaration.
  730.  
  731. $get_structure_head([atom(Atid), atom('/'), atom(sig)|Rest],
  732.                     Atid/Spec, Leftover) :- !,
  733.         $get_speclist(Rest, Spec, [atom('=')|Leftover]).
  734. % ie.  structure X/sig ... end = ... .
  735.  
  736. $get_structure_head([atom(Atid), atom('/'), atom(Sig), atom('=')|Rest],
  737.                     Atid/Sig, Rest) :- !.
  738. % ie.  structure X/Y = ... .
  739.  
  740. $get_structure_head([atom(Atid), atom('=')|Rest], Atid, Rest) :- !.
  741. % ie.  structure X = ... .
  742.  
  743. $get_structure_head([atom(Atid)|_], _, _) :- !,
  744.         $writename('** Read Error : Bad header in structure declaration for '),
  745.         $writename(Atid), $nl, fail.
  746.  
  747. $get_structure_head(_, _, _) :-
  748.         $writename('** Read Error : Bad header in structure declaration'),
  749.     $nl, fail.
  750.  
  751. % $get_functor_head/3
  752. %
  753. % Accept the head of a functor declaration.
  754.  
  755. $get_functor_head([atom(Atid), '('|Rest], Head, Left) :-
  756.         $get_functor_args(Rest, Args, Leftover),
  757.         ( Leftover = [atom('/'), atom(sig)|Tail] ->
  758.                 $get_speclist(Tail, Spec, [atom('=')|Left]) ;
  759.                 ( Leftover = [atom('/'), atom(Spec), atom('=')|Left] ->
  760.                         true ;
  761.                         ( Spec = $dummy,
  762.                           Leftover = [atom('=')|Left]) ) ),
  763.         $univ(Head0, [Atid|Args]),
  764.         ( Spec = $dummy -> Head = Head0 ;
  765.                            Head = Head0/Spec ), !.
  766.  
  767. $get_functor_head([atom(Atid)|_], _, _) :- !,
  768.         $writename('** Read Error : Bad header in functor declaration for '),
  769.         $writename(Atid), $nl, fail.
  770.  
  771. $get_functor_head(_, _, _) :- !,
  772.         $writename('** Read Error : Bad header in functor declaration'),
  773.     $nl, fail.
  774.  
  775. % $get_functor_args/3
  776. %
  777. % Read in the arguments to a functor. Note that these can themselves be
  778. % structures.
  779.  
  780. $get_functor_args([atom(Atid), atom('/'), atom(Sig)|Rest],
  781.                   [Result|Args], Left) :-
  782.         ( Sig == sig -> $get_speclist(Rest, Spec, Leftover) ;
  783.                         ( Sig = Spec,
  784.                           Leftover = Rest ) ),
  785.         ( Leftover = [')'|Left] -> 
  786.                 ( Args = [],
  787.           Result = Atid/Spec ) ;
  788.         ( Leftover = [atom('sharing')|More] ->
  789.             $get_functor_sharing(More, Atid, Spec, Left, Result) ;
  790.                     ( Leftover = [','|More],
  791.               Result = Atid/Spec, !,
  792.                       $get_functor_args(More, Args, Left) ) ) ), !.
  793.  
  794. $get_functor_args(_, _, _) :-
  795.         $writename('** Read Error : Bad functor arguments'), $nl, fail.
  796.  
  797. % $get_functor_sharing/4
  798. %
  799. % Read in the sharing portion of a functors argument list.
  800.  
  801. $get_functor_sharing(More, Atid, Spec, Leftover, sharing(Atid/Spec,Result)) :-
  802.     $append(Read, [')'|Leftover], More),
  803.     $read(Read, 1200, Result, [], perv).
  804.  
  805. $get_functor_sharing(_, _, _, _, _) :-
  806.     $writename('** Read Error : Bad sharing constraint in functor arguments'),
  807.         $nl, fail.
  808.  
  809. % $get_strexpr/4
  810. %
  811. % Read in a strexpr (the body of a structure).
  812.  
  813. $get_strexpr([atom(struct)|Rest], Body, Sig, Leftover) :- !,
  814.         $get_structure_body(Rest, Body, Sig, Leftover).
  815.  
  816. $get_strexpr([atom(Atid),'('|Rest], Body, Sig, Leftover0) :- !,
  817.         $get_strexpr_args(Rest, Args, Leftover),
  818.         $univ(Body, [Atid|Args]),
  819.         ( Leftover = [] -> 
  820.                 ( Sig = $dummy,
  821.                   Leftover0 = [] ) ;
  822.                 ( Leftover = [atom('/'), atom(sig)|Tokens] ->
  823.                         $get_speclist(Tokens, Sig, Leftover0) ;
  824.                         Leftover = [atom('/'), atom(Sig)|Leftover0]) ).
  825.  
  826. $get_strexpr(Tokens, Body, Sig, Leftover) :-
  827.     $get_strexpr_id(Tokens, Body, Left),
  828.     ( Left = [atom('/'),atom(sig)|Rest] ->
  829.           $get_speclist(Rest, Sig, Leftover) ;
  830.           ( Left = [atom('/'),atom(Sig)|Leftover] ->
  831.            true ;
  832.            ( Leftover = Left,
  833.              Sig = $dummy ) ) ).
  834.  
  835. % $get_strexpr_id/3
  836. %
  837.  
  838. $get_strexpr_id([atom(Id),atom(':'),atom(Id1),atom(':')|Rest],
  839.             Id:Path, Leftover) :- !,
  840.     $get_strexpr_id([atom(Id1),atom(':')|Rest], Path, Leftover).
  841. $get_strexpr_id([atom(Id),atom(':'),atom(Id1)|Rest], Id:Id1, Rest) :- !.
  842. $get_strexpr_id([atom(Id)|Rest], Id, Rest).
  843.  
  844. % $get_structure_body/4
  845. %
  846. % Read a structure body (within struct .. end delimiters) into a list.
  847.  
  848. $get_structure_body([atom(end), atom('/'), atom(sig)|Rest], [], Sig, 
  849.                     Leftover) :- !,
  850.         $get_speclist(Rest, Sig, Leftover).
  851. % Check for trailing signature.
  852.  
  853. $get_structure_body([atom(end), atom('/'), atom(Atid)|Leftover], [], Atid,
  854.                     Leftover) :- !.
  855. % Check for trailing signature.
  856.  
  857. $get_structure_body([atom(end)|Leftover], [], $dummy, Leftover) :- !.
  858.  
  859. $get_structure_body([atom(end_of_file)|_], _, _, _) :- !,
  860.         $writename('** Read Error : Unexpected end-of-file in structure body'),
  861.     $nl, fail.
  862.  
  863. $get_structure_body(Tokens0, [Term|List], Sig, Leftover) :-
  864.         $read_on_failure(Tokens0, Tokens),
  865.         $process_tokens(Tokens, Term), !,
  866.              % Recursive call here as structure can contain nested structures.
  867.         $get_structure_body(List, Sig, Leftover).
  868.  
  869. $get_structure_body(List, Sig, Leftover) :-
  870.         $read_tokens(Tokens, _),
  871.         $get_structure_body(Tokens, List, Sig, Leftover).
  872.  
  873. % $get_structure_args/3
  874. %
  875. % Read arguments to a functor application.
  876.  
  877. $get_strexpr_args(Tokens, [Arg0|Args], Left) :-
  878.         $get_strexpr(Tokens, Arg, Sig, Leftover),
  879.         ( Sig = $dummy -> Arg0 = Arg ;
  880.                           Arg0 = Arg/Sig ),
  881.         ( Leftover = [')'|Left] -> 
  882.                 Args = [] ;
  883.                 ( Leftover = [','|More], !,
  884.                   $get_strexpr_args(More, Args, Left) ) ), !.
  885.  
  886. $get_strexpr_args(_, _, _, _) :-
  887.         $writename('** Read Error : Bad arguments in functor application expression'),
  888.         $nl, fail.
  889.